package sword.chapter5HashMap;

import java.util.HashMap;

/**
 * LRUCache
 * <p>
 * 节点是双向链表
 * map的key存键，value存节点；节点key存键，value存值
 * cache头尾哨兵节点，容量大小，map
 *
 * @author K
 * @date 2021-12-01 21:23
 */
public class S31LRUCache {
    HashMap<Integer, ListNode> map;
    ListNode head;
    ListNode tail;
    int capacity;

    S31LRUCache(int capacity) {
        this.capacity = capacity;
        this.map = new HashMap<>(capacity);
        head = new ListNode(-1, -1);
        tail = new ListNode(-1, -1);
        head.next = tail;
        tail.prev = head;
    }

    public Integer get(int key) {
        ListNode listNode = map.get(key);
        if (listNode == null) {
            return -1;
        }
        moveToTail(listNode, listNode.value);
        return listNode.value;
    }

    public void put(int key, int value) {
        if (map.containsKey(key)) {
            moveToTail(map.get(key), value);
        } else {
            if (map.size() == capacity) {
                ListNode toBeDelete = head.next;
                deleteCurrentNode(toBeDelete);
                map.remove(toBeDelete.key);
            }
            ListNode node = new ListNode(key, value);
            insertToTail(node);
            map.put(key, node);
        }
    }

    /**
     * 移动到尾节点
     */
    private void moveToTail(ListNode node, int value) {
        deleteCurrentNode(node);
        node.value = value;
        insertToTail(node);
    }

    /**
     * 加入到尾节点
     */
    private void insertToTail(ListNode node) {
        tail.prev.next = node;
        node.prev = tail.prev;
        node.next = tail;
        tail.prev = node;

        tail.next = head;
        head.prev = tail;
    }

    /**
     * 删除当前节点
     */
    private void deleteCurrentNode(ListNode node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    public static void main(String[] args) {
        S31LRUCache cache = new S31LRUCache(4);
        cache.put(1, 1);
        cache.put(2, 2);
        cache.put(3, 3);
        cache.put(4, 4);

        cache.get(2);

        cache.put(1, 8);

        cache.put(5, 5);
        System.out.println();
    }
}

class ListNode {
    public int key;
    public int value;
    public ListNode next;
    public ListNode prev;

    public ListNode(int k, int v) {
        key = k;
        value = v;
    }
}